package com.fingard.dsp.bank.directbank.psbc01;

import java.io.File;
import java.util.Calendar;
import java.util.Date;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.dsp.bank.reqrespobj.single.detail.ReqPayRecDetail;
import com.fingard.io.FileHelper;
import com.fingard.net.ConnState;
import com.fingard.net.FtpReceiver;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

public class PSBC01BatPayRec extends PSBC01Base implements IBatPayRec {

	// 批量代付，采用流处理方式
	public RetAtsBatPayRec d_1988_BatPay(ReqBatPayRec p_req1988) throws Exception {
		// 返回ATS的对象
		return d_BatPayRec(p_req1988);
	}

	public RetAtsBatPayRec d_9188_BatPay(ReqBatPayRec p_req9188) throws Exception {
		return d_BatPayRec(p_req9188);
	}

	/**
	 * 批量代收付
	 * 
	 * @param p_req
	 * @return 资金系统报文
	 * @throws Exception
	 */
	private RetAtsBatPayRec d_BatPayRec(ReqBatPayRec p_req) throws Exception {
		RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_req.reqHeader);
		retAts.reqSeqID = p_req.reqBatchNO;
		retAts.writeStart();
		boolean isRec = true;
		if ("1988".equals(p_req.reqHeader.transType)) {
			isRec = false;
		} else {
			isRec = true;
		}

		// 文件名组成：文件种类（3位）+委托单位代码（12位）+业务代码（6位）+日期（8位）+序号（5位）+.V（方向标识）
		String basePath = getDataFileDirectory(new Date()) + File.separator;
		String filePath = getDataFileDirectory(new Date()) + File.separator + "BatPayRec";

		int maxBatch = 0;
		File dataFileDir = new File(filePath);
		if (dataFileDir.exists()) {
			int len = dataFileDir.listFiles().length;
			if (len > 0) {
				maxBatch = len + 1;
			} else {
				maxBatch = 1;
			}
		} else {
			maxBatch = 1;
		}
		String filetype = "PCK";// PCK 批量代付
		String busMode = getBankConfig().getValueAsString("opeCodePay");
		if (isRec) {
			filetype = "PKK";// PKK 批量代收
			busMode = getBankConfig().getValueAsString("opeCodeRec");
		}
		String postdate = Format.Date8Format.format(new Date());
		// 文件种类（3位）+委托单位代码（12位）+业务代码（6位）+日期（8位）+序号（5位）+.V（方向标识）
		String fileName = filetype + bankFront.org + busMode + postdate + String.format("%5s", maxBatch).replace(" ", "0") + ".i";
		StringBuilder dealContent = new StringBuilder();
		// “0”不检查证件(不验证时候，证件种类送00)，“1”检查证件，“5”校验证件号码（不验证件类型），“6”校验户名（只验户名，不验证件，不验证时，证件种类送00），“7”校验户名和证件种类和号码，“8”校验户名和证件号码（不校验证件类型）
		dealContent.append(String.format("%8s", p_req.totalNum)).append("|").append(String.format("%15s", p_req.totalAmt)).append("|6|\n");
		StringBuilder sb = new StringBuilder();
		sb.append(fileName).append("\n");
		int num = 1;
		while (p_req.readRecord()) {
			ReqPayRecDetail reqDetail = p_req.readedDetail;
			sb.append(reqDetail.askNumber).append("|");
			String oppAct = reqDetail.recAct;
			String oppNm = reqDetail.recName;
			if (isRec) {
				oppAct = reqDetail.payAct;
				oppNm = reqDetail.payName;
			}
			String cardType = "2";
			String sameBnk = "0";
			if ("0".equals(reqDetail.sameBnk)) {
				sameBnk = "1";
			}
			if ("1".equals(reqDetail.cardType)) {
				cardType = "1";
			}
			dealContent.append(String.format("%8s", num)).append("|");// 序号
			dealContent.append(String.format("%50s", oppAct)).append("|");// 用户号码
																			// 没有填账号
			if (isRec) {
				dealContent.append(String.format("%6s", postdate.substring(0, 6))).append("|");// 扣费月份}
			}
			dealContent.append(cardType).append("|");// 折卡标志 “1”折 ；“2”卡 5-信用卡
			dealContent.append(sameBnk).append("|");// 本他行标志 “0”本行，“1”他行
			dealContent.append(String.format("%32s", oppAct)).append("|");// 账号/卡号
			dealContent.append(String.format("%15s", reqDetail.payAmount)).append("|");// 交易金额
			dealContent.append("00").append("|");// 证件种类
			dealContent.append(String.format("%30s", reqDetail.certNum)).append("|");// 证件种类
			dealContent.append(String.format("%60s", oppNm)).append("|");// 户名
			dealContent.append(String.format("%4s", " ")).append("|");// 摘要
			if (isRec) {
				dealContent.append(String.format("%15s", "0.00")).append("|");// 滞纳金}
				dealContent.append("1").append("|");// 非足额扣款标志送0，足额送1}
			}
			dealContent.append("\n");
			num++;
		}
		FileHelper.writeFile(basePath + File.separator + p_req.reqBatchNO + ".txt", sb.toString(), getCharset());
		FileHelper.writeFile(filePath + File.separator + fileName, dealContent.toString(), getCharset());

		FtpReceiver ftpReceiver = fileUpload(filePath, fileName);// 发送银行

		if (ConnState.FAIL.equals(ftpReceiver.connState) || !ftpReceiver.isCompleted) {
			retAts.respCode = "0";
			retAts.respInfo = "支付文件上传失败";
			retAts.transState = "Upload Failed";
			retAts.payInfoCode = "Upload Failed";
			retAts.writeRetToATS();
			return retAts;
		}

		// 赋值通用参数
		PSBC01Header bankHeader = new PSBC01Header();
		XmlTextWriter xmlWriter = new XmlTextWriter();// 发银行报文的XML对象
		xmlWriter.autoFormat = false;// 报文串需要整个字符串传送，中间需无回车符，否则会签名出错
		bankHeader.OpName = "2030";
		bankHeader.Outsys_Code = "";
		bankHeader.OpDate = postdate;
		writeCommonHeader(xmlWriter, bankHeader);
		// 需要进行对账码拼接以及节点解析，采用XElement进行处理
		XElement tmpXElement = new XElement("Param", "");
		// 定义2030支付类型报文
		String type = "1";// 0-代收 1-代付
		if (isRec) {
			type = "0";
		}
		tmpXElement.addChild(new XElement("Function", type));// 交易类型 Char(1)
		tmpXElement.addChild(new XElement("Merch_Id", bankFront.org));// 集团客户号
																		// Char(12)
		tmpXElement.addChild(new XElement("Ope_Code", "0103"));// 业务代码 Char(6)
		tmpXElement.addChild(new XElement("Cust_Acct", p_req.ownAct));// 公司结算账户
																		// Char(32)
		tmpXElement.addChild(new XElement("File_Name", fileName));// 文件名
																	// Char(60)
		tmpXElement.addChild(new XElement("Reserved1", ""));// 备用字段1 Char(40)
		tmpXElement.addChild(new XElement("Reserved2", ""));// 备用字段2 Char(40)
		tmpXElement.addChild(new XElement("Reserved3", ""));// 备用字段3 Char(40)
		tmpXElement.addChild(new XElement("Reserved4", ""));// 备用字段4 Char(40)
		xmlWriter.writeXElement(tmpXElement);
		xmlWriter.writeEndDocument();// 写入报文完成
		System.out.println("dsp接收报文：" + xmlWriter.toXmlString());// 测试代码：打印接收报文
		String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());// 发送银行
		// 测试代码
		// String[] tmpStrRet = {"",""};
		// tmpStrRet[0]="";
		// tmpStrRet[1]="<?xml version=\"1.0\" encoding =\"GBK\"?><root><Head><OpName>2020</OpName><OpRetCode>00</OpRetCode><OpRetMsg></OpRetMsg></Head><Param><Result></Result><Bank_Serial>00212010212</Bank_Serial><Trans_Date>20140301</Trans_Date><Reserved1></Reserved1><Reserved2></Reserved2><Reserved3></Reserved3><Reserved4></Reserved4></Param></root>";
		if (tmpStrRet[0].length() == 0) {
			StringBuilder tmpSbMsg = new StringBuilder();
			// 解析银行返回
			XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
			if (tmpBkReader != null) {
				retAts.respCode = "0";
				String tmpHeadCode = tmpBkReader.getFirstText("/root/Head/OpRetCode");// 00：成功
																						// 01失败
				String tmpBodyCode = tmpBkReader.getFirstText("/root/body/OpRetCode");// 返回码2位：00：成功
																						// 其他：失败
				if (tmpBodyCode != null && !"".equals(tmpBodyCode)) {
					tmpHeadCode = tmpBodyCode;
				}
				String tmpHeadMsg = tmpBkReader.getFirstText("/root/Head/OpRetMsg");
				String tmpBodyMsg = tmpBkReader.getFirstText("/root/body/OpRetMsg");// 返回码对应的文字信息
				if (tmpBodyMsg != null && !"".equals(tmpBodyMsg)) {
					tmpHeadMsg = tmpBodyMsg;
				}
				String result = tmpBkReader.getFirstText("/root/Param/Result");// 0：失败
																				// 1：成功
																				// 2：不确定
				retAts.transState = tmpHeadCode + "+" + result;
				retAts.payInfoCode = retAts.transState;
				retAts.respInfo = tmpHeadMsg;
			} else {
				retAts.respCode = "-1";
				retAts.respInfo = tmpSbMsg.toString();
			}
		} else if (tmpStrRet[0].equals(ConnState.FAIL)) {
			retAts.respCode = "0";
			retAts.respInfo = tmpStrRet[1];
			retAts.transState = PaymentState.FAIL_Payment;
			retAts.payInfoCode = tmpStrRet[0];
		} else {
			retAts.respCode = "-1";
			retAts.respInfo = tmpStrRet[1];
		}
		return retAts;
	}

	// 1998 状态查询
	public RetAtsQryBatPayRec d_1998_QryBatPay(ReqQryBatPayRec p_req1998) throws Exception {
		return d_QryBatPayRec(p_req1998);
	}

	public RetAtsQryBatPayRec d_9198_QryBatPay(ReqQryBatPayRec p_req9198) throws Exception {
		return d_QryBatPayRec(p_req9198);
	}

	/**
	 * 批量代收付查询
	 * 
	 * @param p_req
	 * @return 资金系统报文
	 * @throws Exception
	 */
	private RetAtsQryBatPayRec d_QryBatPayRec(ReqQryBatPayRec p_req) throws Exception {
		boolean isRec = false;
		if ("9198".equals(p_req.reqHeader.transType)) {
			isRec = true;
		}
		// //返回ATS的对象
		RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_req.reqHeader);
		retAts.reqSeqID = p_req.reqBatchNO;
		retAts.writeStart();
		Calendar cal = Calendar.getInstance();
		cal.setTime(p_req.getBgnDateTime());
		String basePath = getDataFileDirectory(cal.getTime()) + File.separator;
		File mapFile = new File(basePath + File.separator + p_req.reqBatchNO + ".txt");
		if (!mapFile.exists()) {
			retAts.respCode = "-1";
			retAts.respInfo = "序号-流水映射文件不存在，请联系开发人员";
			retAts.writeAfterDetail();
			return retAts;
		}
		String filecontent = FileHelper.readToString(mapFile, getCharset());
		String[] idxMap = filecontent.split("\n");
		StringBuilder filename = new StringBuilder(idxMap[0]);
		// 文件名：批量和批量结果文件除了方向标志不一样外，其他一致。请求的方向是.i,响应文件的.o。
		filename.replace(filename.length() - 1, filename.length(), "o");

		File receiveFile = new File(basePath + File.separator + filename.toString());

		for (int n = 0; n < 4; n++) {
			if (receiveFile.exists()) {
				// PCK 批量代付 PKK 批量代收
				WriteBankLogLn("银行返回结果文件:" + basePath + File.separator + filename.toString());
				String result = FileHelper.readToString(receiveFile, getCharset());
				// PCK 批量代付
				// 文件头：交易总笔数|交易总金额|成功笔数|成功金额|失败笔数|失败金额|总异地手续费|总业务手续费|清算日期|\n
				// 文件体：序号|用户号码|折卡标志|本他行标志|账号/卡号|录入交易金额|交易金额|证件种类|证件号码|户名|摘要|应答码|响应描述|异地手续费|业务手续费|\n
				// PKK 批量代收
				// 文件头：交易总笔数|交易总金额|成功笔数|成功金额|失败笔数|失败金额|总异地手续费|总业务手续费|清算日期|\n
				// 文件体：序号|应答码|折卡标志|本他行标志|账号/卡号|用户号码|户名|摘要|滞纳金|扣款金额|异地手续费|业务手续费|响应信息描述|\n
				String[] idx = idxMap[1].split("\\|");
				String[] tmpMsg = result.split("\n");
				for (int x = 1; x < tmpMsg.length; x++) {
					RetAtsBatPayRecDetail retDetail = new RetAtsBatPayRecDetail();
					String[] resDetail = tmpMsg[x].split("\\|");
					retDetail.postScript = idx[x - 1];
					String status = resDetail[11];
					String retMsg = resDetail[12];
					if (isRec) {
						status = resDetail[1];
						retDetail.payAct = resDetail[4];
						retDetail.payName = resDetail[6];
					} else {
						retDetail.recAct = resDetail[4];
						retDetail.recName = resDetail[9];
					}
					retDetail.result = status;// 应答码 4
					retDetail.payInfoCode = status;// 应答码 4
					retDetail.memo = retMsg;// 应答码 4
					retAts.writeRetDetail(retDetail);
				}
				break;
			} else {
				WriteBankLogLn("未找到结果文件:" + basePath + File.separator + filename.toString());
				retAts.respCode = "-1";
				retAts.respInfo = "银行还未返回结果文件";
			}
			cal.add(Calendar.DAY_OF_YEAR, 1);
			if (cal.getTimeInMillis() > System.currentTimeMillis()) {
				break;
			}
			basePath = getDataFileDirectory(cal.getTime());
			receiveFile = new File(basePath + File.separator + filename.toString());
		}
		retAts.writeAfterDetail();
		return retAts;
	}

}
